// This is core/vnl/algo/vnl_brent.cxx

#include <cassert>
#include "vnl_brent.h"
#include <vnl/algo/vnl_bracket_minimum.h>

vnl_brent::vnl_brent(vnl_cost_function* functor)
  : vnl_brent_minimizer( *functor )
{
}

vnl_brent::~vnl_brent() = default;

double vnl_brent::minimize_given_bounds(double ax, double bx, double cx,
                                        double tol,
                                        double *xmin)
{
  assert( xmin != nullptr );
  this->set_x_tolerance( tol );
  *xmin = vnl_brent_minimizer::minimize_given_bounds( ax, bx, cx );
  return vnl_brent_minimizer::f_at_last_minimum();
}

double vnl_brent::minimize_given_bounds_and_1st_f(double ax, double bx,
                                                  double fb, double cx,
                                                  double tol, double *xmin)
{
  assert( xmin != nullptr );
  this->set_x_tolerance( tol );
  *xmin = vnl_brent_minimizer::minimize_given_bounds_and_one_f( ax, bx, cx, fb );
  return vnl_brent_minimizer::f_at_last_minimum();
}


void vnl_brent::bracket_minimum(double *ax, double *bx, double *cx)
{
  double fa, fb, fc;
  bracket_minimum(ax,bx,cx,&fa,&fb,&fc);
}

void vnl_brent::bracket_minimum(double *ax, double *bx, double *cx,
                                double *fa, double *fb, double *fc)
{
  vnl_bracket_minimum( *f_, *cx, *bx, *ax, *fc, *fb, *fa );
}


double vnl_brent::minimize(double x)
{
  double ax=x-1.0;
  double xx=x+1.0;
  double bx = 0.0;
  double fa,fx,fb;
  bracket_minimum(&ax,&xx,&bx,&fa,&fx,&fb);
  minimize_given_bounds(bx,xx,ax,ftol,&x);
  return x;
}
